home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Graphics 2D / Band Copying the Sequel / Band Copying the Sequel.c next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  13.1 KB  |  440 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        Band Copying the Sequel.c
  3.  
  4.     Contains:    Under low memory conditions, it's often necessary        
  5.                 to draw an image by individual bands rather than        
  6.                 to draw the entire image at once, and in most cases        
  7.                 this method works fine unless the image requires        
  8.                 dithering from its source to its destination.  The        
  9.                 purpose of this app is to show the problem that may        
  10.                 occur when copying these individual bands and to        
  11.                 provide one possible solution.    
  12.  
  13.     Written by: EL    
  14.  
  15.     Copyright:    Copyright © 1991-999 by Apple Computer, Inc., All Rights Reserved.
  16.  
  17.                 You may incorporate this Apple sample source code into your program(s) without
  18.                 restriction. This Apple sample source code has been provided "AS IS" and the
  19.                 responsibility for its operation is yours. You are not permitted to redistribute
  20.                 this Apple sample source code as "Apple sample source code" after having made
  21.                 changes. If you're going to re-distribute the source, we require that you make
  22.                 it clear in the source that the code was descended from Apple sample source
  23.                 code, but that you've made changes.
  24.  
  25.     Change History (most recent first):
  26.                 08/2000        JM                Carbonized, non-Carbon code is commented out
  27.                                             for demonstration purposes.
  28.                 7/8/1999    KG                Updated for Metrowerks Codewarror Pro 2.1
  29.                 11/03/91    EL                Created                        
  30. */
  31. #include "CarbonPrefix.h"
  32. #include <Dialogs.h>
  33. #include <Fonts.h>
  34. #include <Resources.h>
  35. #include <QDOffscreen.h>
  36. #include <TextUtils.h>
  37. #include <Quickdraw.h>
  38. /* Constant Declarations */
  39.  
  40. #define    WWIDTH        330        /* Window width for the color and b/w images. */
  41. #define    WHEIGHT        300        /* Window height for the color and b/w images. */
  42.  
  43. //#define WLEFT        (((qd.screenBits.bounds.right - qd.screenBits.bounds.left) - WWIDTH) / 2)
  44. //#define WTOP        (((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - WHEIGHT) / 2)
  45.  
  46. #define TOTALBANDS    25        /* Total number of bands to separate Pict into. */
  47. #define    PADHEIGHT    8        /* Padding to add above band in pixels. */
  48. #define    SCALING        4        /* Scale source by factor of... */
  49.  
  50. #ifndef topLeft
  51. #define topLeft(r)                      (((Point *) &(r))[0])
  52. #endif
  53.  
  54. #ifndef botRight
  55. #define botRight(r)                     (((Point *) &(r))[1])
  56. #endif
  57.  
  58. /* Global Variable Definitions */
  59.  
  60. WindowPtr        gCWindow;
  61. WindowPtr        gWindow;
  62.  
  63. GWorldPtr        gGWorld;
  64. PixMapHandle    gPixMap;
  65.  
  66. PicHandle        gPict;                /* Pict resource used for test. */
  67. int                gPictWidth;            /* Width of pict resource. */
  68. int                gPictHeight;        /* Height of pict resource. */
  69. int                gBandStart;            /* Starting band number to draw. */
  70. int                gBandEnd;            /* Ending band number to draw. */
  71. int             gBandHeight;        /* Thickness of band in pixels. */
  72. int                gPadding = 0;        /* Current value of padding. */
  73.  
  74. void initMac();            /* Initializes the environment. */
  75. void initPictInfo();    /* Initializes the picture information. */
  76.  
  77. void createWindows();    /* Creates windows for color and b/w images. */
  78. void createGWorld();    /* Creates 1 bit offscreen GWorld used for dithering. */
  79. void drawCWindow();        /* Displays the original color image. */
  80. void drawBwWindow();    /* Displays the dithered/enlarged b/w image. */
  81. void doBandCopy();        /* Copies image by individual bands. */
  82. void doNoBandCopy();    /* Copies the entire image at once without bands. */
  83. void drawMessage();        /* Draws text in color window. */
  84.  
  85. void doEventLoop();        /* Handles all events. */
  86.  
  87. void main(void)
  88. {
  89.     initMac();
  90.     initPictInfo();
  91.  
  92.     createWindows();
  93.     createGWorld();
  94.     
  95.     doEventLoop();
  96. }
  97.  
  98. void initMac()
  99. {
  100.     /*MaxApplZone();
  101.     
  102.     InitGraf( &qd.thePort );
  103.     InitFonts();
  104.     InitWindows();
  105.     InitMenus();
  106.     TEInit();
  107.     InitDialogs( nil );*/
  108.     
  109.     InitCursor();
  110.     FlushEvents( 0, everyEvent );    
  111. }
  112.  
  113. void initPictInfo()
  114. {
  115.     gPict = (PicHandle)GetResource( 'PICT', 128 );
  116.  
  117.     gPictWidth = (**gPict).picFrame.right - (**gPict).picFrame.left;
  118.     gPictHeight = (**gPict).picFrame.bottom - (**gPict).picFrame.top;
  119.     
  120.     gBandStart = 0;                                /* Start at band number 0. */
  121.     gBandEnd = 0;                                /* End at band number 0. */
  122.     gBandHeight = gPictHeight / TOTALBANDS;
  123. }
  124.  
  125. void createWindows()
  126. {
  127.     Rect rect;
  128.     int                left, top;
  129.     BitMap            tempBitMap;    //used in carbonization
  130.     
  131.     GetQDGlobalsScreenBits(&tempBitMap);
  132.     
  133.     left = (((tempBitMap.bounds.right - tempBitMap.bounds.left) - WWIDTH) / 2);
  134.     top = (((tempBitMap.bounds.bottom - tempBitMap.bounds.top) - WHEIGHT) / 2);
  135.     
  136.     //SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  137.     SetRect( &rect, left, top, left + WWIDTH, top + WHEIGHT );
  138.     
  139.     OffsetRect( &rect, -((WWIDTH + 10) / 2), 0 );
  140.     gCWindow = NewCWindow( 0L, &rect, "\pBand Copying the Sequel", true, documentProc,
  141.                             (WindowPtr)-1L, false, 0L );
  142.     
  143.     OffsetRect( &rect, WWIDTH + 10, 0 );
  144.     gWindow = NewCWindow( 0L, &rect, "\pBandCopying ON - Padding OFF", true, documentProc,
  145.                             (WindowPtr)-1L, true, 0L );
  146.                             
  147.     //SetPort( gCWindow );
  148.     SetPortWindowPort( gCWindow );
  149. }
  150.  
  151. void createGWorld()
  152. {
  153.     /*int        i;*/
  154.     /*Rect    rect;*/
  155.     Rect    tempRect1;    //used in carbonization
  156.     
  157.     /* Create a 1bit offscreen gWorld to be used for B/W dithering. */
  158.  
  159.     //NewGWorld( &gGWorld, 1, &gWindow->portRect, nil, nil, 0 );
  160.     NewGWorld( &gGWorld, 1, GetPortBounds(GetWindowPort(gWindow), &tempRect1), nil, nil, 0 );
  161.     gPixMap = GetGWorldPixMap( gGWorld );
  162. }
  163.  
  164. void drawCWindow()
  165. {
  166.     Rect    rect;
  167.     RGBColor    black = {0, 0, 0};
  168.     RGBColor    oldColor;
  169.     int        row;
  170.     
  171.     /* Reposition the picture's rect then draw it into the first window. */
  172.     
  173.     //SetPort( gCWindow );
  174.     SetPortWindowPort( gCWindow );
  175.     GetPortForeColor(GetWindowPort(gCWindow) , &oldColor);
  176.     
  177.     rect.left = (WWIDTH - gPictWidth) / 2;
  178.     rect.top = (WHEIGHT - gPictHeight) / 2;
  179.     rect.right = rect.left + gPictWidth;
  180.     rect.bottom = rect.top + gPictHeight;
  181.     
  182.     DrawPicture( gPict, &rect );
  183.     
  184.     TextFont( kFontIDHelvetica );
  185.     TextSize( 12 );
  186.     RGBForeColor(&black);
  187.     
  188.     row = 20;    
  189.     drawMessage( &row, "\p• Click the mouse button in the" );
  190.     drawMessage( &row, "\p   b/w window to draw another band." );
  191.     drawMessage( &row, "\p• Press any key other than ESC to toggle between" );
  192.     drawMessage( &row, "\p   using band copying with or without padding." );
  193.     
  194.     row = 200;    
  195.     drawMessage( &row, "\p• Press ESC to toggle between using copybits" );
  196.     drawMessage( &row, "\p   with or without bands." );
  197.     
  198.     RGBForeColor(&oldColor);
  199. }
  200.  
  201. void drawMessage( row, string )
  202. int        *row;
  203. Str255    string;
  204. {
  205.     MoveTo( 10, *row += 15 );
  206.     DrawString(  string );
  207. }
  208.  
  209. void drawBwWindow()
  210. {
  211.     Rect rect;
  212.     Rect tempRect1;
  213.     
  214.     if (gPadding >= 0)
  215.     {
  216.         SetRect( &rect, 0, 0, gPictWidth * SCALING, (gBandHeight + gPadding) * SCALING );
  217.         UpdateGWorld( &gGWorld, 1, &rect, nil, nil, stretchPix );
  218.         gPixMap = GetGWorldPixMap( gGWorld );
  219.         doBandCopy();
  220.     }
  221.     else
  222.     {
  223.         //UpdateGWorld( &gGWorld, 1, &gWindow->portRect, nil, nil, stretchPix );
  224.         UpdateGWorld( &gGWorld, 1, GetPortBounds(GetWindowPort(gWindow), &tempRect1), nil, nil, stretchPix );
  225.         gPixMap = GetGWorldPixMap( gGWorld );
  226.         doNoBandCopy();
  227.     }
  228. }
  229.  
  230. void doBandCopy()
  231. {
  232.     int            i;
  233.     int            hoffset, voffset;    /* Starting position of picture in b/w window. */
  234.     Rect        colorRect;            /* Source rect for the color image band. */
  235.     Rect        gworldRect;            /* Source/destinaton rect for the gworld image band. */
  236.     Rect        bwRect;                /* Destination rect for the b/w image band. */
  237.     CGrafPtr    currentPort;        /* CGrafPort of window. */
  238.     GDHandle    currentGDevice;        /* GDevice used by window. */
  239.     Str255        string;
  240.         
  241.     hoffset = (WWIDTH - gPictWidth) / 2;
  242.     voffset = (WHEIGHT - gPictHeight) / 2;
  243.  
  244.     //SetPort( gWindow );
  245.     SetPortWindowPort( gWindow );
  246.     TextFont( kFontIDHelvetica );
  247.     TextSize( 9 );
  248.  
  249.     GetGWorld( ¤tPort, ¤tGDevice );
  250.  
  251.     for (i = gBandStart; i <= gBandEnd; i++)
  252.     {
  253.         SetGWorld( gGWorld, nil );
  254.  
  255.         /* Define the source band rect for the color image, */
  256.         /*    INCLUDING any padding if applicable.            */
  257.         colorRect.left = hoffset;
  258.         colorRect.right = hoffset + gPictWidth;
  259.         colorRect.top = voffset + (i * gBandHeight) - gPadding;
  260.         colorRect.bottom = voffset + (i * gBandHeight) + gBandHeight;
  261.         
  262.         //LocalToGlobal(&topLeft(colorRect));
  263.         //LocalToGlobal(&botRight(colorRect));
  264.         //GlobalToLocal(&topLeft(colorRect));
  265.         //GlobalToLocal(&botRight(colorRect));
  266.         SetPortWindowPort(gCWindow);
  267.         
  268.         /* Define the destination band rect for the gworld dithered image, */
  269.         /*    allow extra space for padding if necessary.                       */
  270.         SetRect( &gworldRect, 0, 0, gPictWidth * SCALING,
  271.                             (gBandHeight + gPadding) * SCALING );
  272.     
  273.         /* Copy the color source into the B/W gworld using dithering. */
  274.         /*  Also, be sure to copy any padded area as well.              */
  275.         //CopyBits( &gCWindow->portBits, (BitMap*)*gPixMap, &colorRect, &gworldRect, ditherCopy, 0l);
  276.         CopyBits( GetPortBitMapForCopyBits(GetWindowPort(gCWindow)), (BitMap*)*gPixMap, &colorRect, &gworldRect, ditherCopy, 0l);
  277.         
  278.         SetGWorld( currentPort, currentGDevice );
  279.         
  280.         /* Now, set the source band rect to the gworld image's EXCLUDING any padding. */
  281.         /*  If padding was used, offset pass the padding and down to the band.        */
  282.         SetRect( &gworldRect, 0, gPadding * SCALING, gPictWidth * SCALING,
  283.                                 (gPadding + gBandHeight) * SCALING );
  284.         
  285.         /* Define the destination band rect for the final b/w image. */
  286.         /*  No padding should apply here!!                             */
  287.         SetRect( &bwRect, hoffset / SCALING,
  288.                         (voffset / SCALING) + ((i * gBandHeight) * SCALING),
  289.                         (hoffset / SCALING) + (gPictWidth * SCALING),
  290.                         (voffset / SCALING) + (((i * gBandHeight) + gBandHeight) * SCALING) );
  291.  
  292.         /* Finally, copy the offscreen image into the B/W window. */
  293.         //CopyBits( (BitMap*)*gPixMap, &gWindow->portBits, &gworldRect, &bwRect, srcCopy, 0l);
  294.         SetPortWindowPort(gWindow);
  295.         CopyBits( (BitMap*)*gPixMap, GetPortBitMapForCopyBits(GetWindowPort(gWindow)), &gworldRect, &bwRect, srcCopy, 0l);
  296.     
  297.         //SetPort( gWindow );
  298.         SetPortWindowPort( gWindow );
  299.         MoveTo( bwRect.right + 3, bwRect.bottom );
  300.         NumToString( i, string );
  301.         DrawString( string );
  302.     }
  303. }
  304.  
  305. void doNoBandCopy()
  306. {
  307.     Rect        colorRect;            /* Source rect for the color image band. */
  308.     /*Rect        gworldRect;            /* Source/destinaton rect for the gworld image band. */
  309.     Rect        bwRect;                /* Destination rect for the b/w image band. */
  310.     int            hoffset, voffset;    /* Starting position of picture in b/w window. */
  311.     CGrafPtr    currentPort;        /* CGrafPort of window. */
  312.     GDHandle    currentGDevice;        /* GDevice used by window. */
  313.     
  314.     GetGWorld( ¤tPort, ¤tGDevice );
  315.     
  316.     hoffset = (WWIDTH - gPictWidth) / 2;
  317.     voffset = (WHEIGHT - gPictHeight) / 2;
  318.  
  319.     colorRect.left = hoffset;
  320.     colorRect.top = voffset;
  321.     colorRect.right = hoffset + gPictWidth;
  322.     colorRect.bottom = voffset + gPictHeight;
  323.  
  324.     SetRect( &bwRect, hoffset / SCALING,
  325.                     voffset / SCALING,
  326.                     (hoffset / SCALING) + (gPictWidth * SCALING),
  327.                     (voffset / SCALING) + (gPictHeight * SCALING) );
  328.     
  329.     SetGWorld( gGWorld, nil );
  330.     SetPortWindowPort(gCWindow);
  331.     //CopyBits( &gCWindow->portBits, (BitMap*)*gPixMap, &colorRect, &bwRect, ditherCopy, 0l);
  332.     CopyBits( GetPortBitMapForCopyBits(GetWindowPort(gCWindow)), (BitMap*)*gPixMap, &colorRect, &bwRect, ditherCopy, 0l);
  333.     SetGWorld( currentPort, currentGDevice );
  334.     SetPortWindowPort(gWindow);
  335.     //CopyBits( (BitMap*)*gPixMap, &gWindow->portBits, &bwRect, &bwRect, srcCopy, 0l);
  336.     CopyBits( (BitMap*)*gPixMap, GetPortBitMapForCopyBits(GetWindowPort(gWindow)), &bwRect, &bwRect, srcCopy, 0l);
  337. }
  338.  
  339. void doEventLoop()
  340. {
  341.     EventRecord event;
  342.     WindowPtr   window;
  343.     short       clickArea;
  344.     Rect        screenRect;
  345.     static int    oldPadding;
  346.     Rect        tempRect1;    //used for carbonization
  347.     
  348.     for (;;)
  349.     {
  350.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  351.         {
  352.             if (event.what == mouseDown)
  353.             {
  354.                 clickArea = FindWindow( event.where, &window );
  355.                 
  356.                 if (clickArea == inDrag)
  357.                 {
  358.                     //screenRect = (**GetGrayRgn()).rgnBBox;
  359.                     GetRegionBounds(GetGrayRgn(), &screenRect );
  360.                     DragWindow( window, event.where, &screenRect );
  361.                 }
  362.                 else if (clickArea == inContent)
  363.                 {
  364.                     if (window != FrontWindow())
  365.                         SelectWindow( window );
  366.                     else
  367.                     {
  368.                         if (gPadding >= 0)
  369.                         {    
  370.                             gBandEnd++;
  371.                             
  372.                             if (gBandEnd > TOTALBANDS)
  373.                             {
  374.                                 gBandEnd = 0;
  375.                                 //SetPort( gWindow );
  376.                                 SetPortWindowPort( gWindow );
  377.                                 //EraseRect( &gWindow->portRect );
  378.                                 EraseRect( GetPortBounds(GetWindowPort(gWindow), &tempRect1 ) );
  379.                             }
  380.                             
  381.                             gBandStart = gBandEnd;
  382.                             drawBwWindow();
  383.                         }
  384.                     }
  385.                 }
  386.                 else if (clickArea == inGoAway)
  387.                     if (TrackGoAway( window, event.where ))
  388.                         return;
  389.             }
  390.             else if (event.what == keyDown || event.what == autoKey)
  391.             {
  392.                 if ((event.message & charCodeMask) == 0x1b)
  393.                 {
  394.                     //SetPort( gWindow );
  395.                     SetPortWindowPort( gWindow );
  396.                     //EraseRect( &gWindow->portRect );
  397.                     EraseRect( GetPortBounds(GetWindowPort(gWindow), &tempRect1 ) );
  398.                     
  399.                     if (gPadding >= 0)
  400.                         gPadding = -1;
  401.                     else
  402.                         gPadding = oldPadding;
  403.                 }
  404.                 
  405.                 if (gPadding == 0)
  406.                 {
  407.                     gPadding = PADHEIGHT;
  408.                     SetWTitle( gWindow, "\pBandCopying ON - Padding ON" );
  409.                     oldPadding = 0;
  410.                 }
  411.                 else if (gPadding > 0)
  412.                 {
  413.                     gPadding = 0;
  414.                     SetWTitle( gWindow, "\pBandCopying ON - Padding OFF" );
  415.                     oldPadding = PADHEIGHT;
  416.                 }
  417.                 else
  418.                     SetWTitle( gWindow, "\pBandCopying OFF" );
  419.                     
  420.                 gBandStart = 0;
  421.                 drawBwWindow();
  422.             }
  423.             
  424.             else if (event.what == updateEvt)
  425.             {
  426.                 window = (WindowPtr)event.message;    
  427.                 //SetPort( window );
  428.                 SetPortWindowPort( window );
  429.                 
  430.                 BeginUpdate( window );
  431.                 
  432.                 gBandStart = 0;
  433.                 drawCWindow();
  434.                 drawBwWindow();
  435.                 
  436.                 EndUpdate( window );
  437.             }
  438.         }
  439.     }
  440. }